/**
 * web.xml
 * <filter>
 * <filter-name>corsFilter</filter-name>
 * <filter-class>com.xxx.api.cors.CorsFilter</filter-class>
 * <init-param>
 * <param-name>allowOrigin</param-name>
 * <param-value>http://web.xxx.com</param-value>
 * </init-param>
 * <init-param>
 * <param-name>allowMethods</param-name>
 * <param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
 * </init-param>
 * <init-param>
 * <param-name>allowCredentials</param-name>
 * <param-value>true</param-value>
 * </init-param>
 * <init-param>
 * <param-name>allowHeaders</param-name>
 * <param-value>Content-Type</param-value>
 * </init-param>
 * </filter>
 * <filter-mapping>
 * <filter-name>corsFilter</filter-name>
 * <url-pattern>/*</url-pattern>
 * </filter-mapping>
 */
package com.honeybees.framework.spring.mvc.filter;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * <dl>
 * <dt><b> CORS 跨域配置 </b></dt>
 * <p>
 * <dd>CORS全称为Cross Origin Resource Sharing（跨域资源共享），服务端只需添加相关响应头信息，即可实现客户端发出AJAX跨域请求。</dd>
 * <dd>CORS技术非常简单，易于实现，目前绝大多数浏览器均已支持该技术（IE8浏览器也支持了），服务端可通过任何编程语言来实现，只要能将CORS响应头写入response对象中即可。</dd>
 * </dl>
 * <p>
 * Copyright (C) All rights reserved.
 * </p>
 * http://blog.csdn.net/coolyqq/article/details/51314388 <br>
 * http://blog.csdn.net/hong_taizi/article/details/49423995 <br>
 * http://www.open-open.com/lib/view/open1463878352785.html
 *
 * @author 李远明
 * @version 2017-01-18 09:32:59
 * @see org.springframework.web.bind.annotation.CrossOrigin
 */
public final class CorsFilter implements Filter {

    private String allowOrigin;
    private String allowMethods;
    private String allowCredentials;
    private String allowHeaders;
    private String exposeHeaders;

    /**
     * {@inheritDoc}
     *
     * @author 李远明
     * @version 2017-01-18 09:32:59
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        allowOrigin = filterConfig.getInitParameter("allowOrigin");
        allowMethods = filterConfig.getInitParameter("allowMethods");
        allowCredentials = filterConfig.getInitParameter("allowCredentials");
        allowHeaders = filterConfig.getInitParameter("allowHeaders");
        exposeHeaders = filterConfig.getInitParameter("exposeHeaders");
    }

    /**
     * {@inheritDoc}
     * <p>
     * 过滤所有的HTTP请求，并将CORS响应头写入response对象中
     *
     * @author 李远明
     * @version 2017-01-18 09:32:59
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        if (StringUtils.isNotEmpty(allowOrigin)) {
            List<String> allowOriginList = Arrays.asList(allowOrigin.split(","));
            if (CollectionUtils.isNotEmpty(allowOriginList)) {
                String currentOrigin = req.getHeader("Origin");
                if (allowOriginList.contains(currentOrigin)) {
                    // Access-Control-Allow-Origin：允许访问的客户端域名，例如：http://web.xxx.com，若为*，则表示从任意域都能访问，即不做任何限制。
                    res.setHeader("Access-Control-Allow-Origin", currentOrigin);
                }
            }
        }
        if (StringUtils.isNotEmpty(allowMethods)) {
            // Access-Control-Allow-Methods：允许访问的方法名，多个方法名用逗号分割，例如：GET,POST,PUT,DELETE,OPTIONS。
            res.setHeader("Access-Control-Allow-Methods", allowMethods);
        }
        if (StringUtils.isNotEmpty(allowCredentials)) {
            // Access-Control-Allow-Credentials：是否允许请求带有验证信息，若要获取客户端域下的cookie时，需要将其设置为true。
            res.setHeader("Access-Control-Allow-Credentials", allowCredentials);
        }
        if (StringUtils.isNotEmpty(allowHeaders)) {
            // Access-Control-Allow-Headers：允许服务端访问的客户端请求头，多个请求头用逗号分割，例如：Content-Type。
            res.setHeader("Access-Control-Allow-Headers", allowHeaders);
        }
        if (StringUtils.isNotEmpty(exposeHeaders)) {
            // Access-Control-Expose-Headers：允许客户端访问的服务端响应头，多个响应头用逗号分割。
            res.setHeader("Access-Control-Expose-Headers", exposeHeaders);
        }
        chain.doFilter(request, response);
    }

    /**
     * {@inheritDoc}
     *
     * @author 李远明
     * @version 2017-01-18 09:32:59
     */
    @Override
    public void destroy() {
    }

}
